package com.dtkavin.threads;

import org.apache.hadoop.hdfs.util.RwLock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by john on 10/4/16.
 */
public class CacheSystem {
    private CacheSystem() {
    }


    private static CacheSystem instance = null;

    /**
     * 饥汉模式
     *
     * @return
     */
    public static synchronized CacheSystem getInstance() {
        if (instance == null) {
            instance = new CacheSystem();
        }
        return instance;
    }

    private Map<String, Object> cache = new HashMap<String, Object>();

    //如果用synchronized，多个读线程也会互斥，所以用readWriteLock对读性格会更高一点
    private ReadWriteLock rwLock = new ReentrantReadWriteLock();

    /**
     * 从缓存系统中读取数据，如果读取不到，则从数据库读取
     * <p>
     * 问题：多个线程都在读，上了3把读锁，其中一个线程首先探测到缓存中没有数据，上写锁，其它的线程读锁还没有释放，可以么？
     *  思考结果：读读不互斥，但读写和写写互斥，有上读锁后是无法写的，需要读锁释放后才可以上写锁
     *
     * @param key
     * @return
     */
    public Object getData(String key) {
        rwLock.readLock().lock();
        Object value = null;
        try {
            value = cache.get(key);
            if (value == null) {
                //确保读写互斥
                rwLock.readLock().unlock();
                rwLock.writeLock().lock();
                try {
                    if ((value = cache.get(key)) == null) {//确保其它线程写完之后不会再重复写
                        value = "aaa";//get from db
                    }
                } finally {
                    rwLock.writeLock().unlock();
                }
                rwLock.readLock().lock();

            }
        } finally {
            rwLock.readLock().unlock();
        }
        return value;
    }


}
